package com.kclmedu.sst.security;

import com.kclmedu.sst.security.exceptions.CheckCodeVerifyException;
import org.apache.log4j.Logger;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/************************
 * 验证码认证的过滤器，我们这里要继承 Spring Security提供的一个父类 OncePerRequestFilter
 * 这个过滤器表示每个请求都将进入这个过滤器
 */
public class CheckCodeAuthenticationFilter extends OncePerRequestFilter {

    private final Logger LOGGER = Logger.getLogger(CheckCodeAuthenticationFilter.class);

    private AuthenticationFailureHandler failureHandler;

    public AuthenticationFailureHandler getFailureHandler() {
        return failureHandler;
    }

    public void setFailureHandler(AuthenticationFailureHandler failureHandler) {
        this.failureHandler = failureHandler;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //
        LOGGER.debug("进入CheckCodeAuthenticationFilter的doFilterInternal方法...");
        //我们只针对在登录请求时才需要验证 这个验证码，所以，先判断
        if(request.getRequestURI().contains("/user_login")) {
            LOGGER.debug("用户发起了登录请求...");
            //对验证码进行输入验证
            try {
                //1. 获取用户输入的验证码, 通过请求来获取
                final String checkcode = request.getParameter("checkcode");
                LOGGER.debug("用户输入的验证码是："+checkcode);
                //2. 获取后台生成的验证码[这个事先已保存在session中]
                String o_code = (String) request.getSession().getAttribute("CHECKCODE");
                //
                LOGGER.debug("在httpsession中存放的验证码是："+o_code);
                //3. 过行比较
                if(checkcode == null || checkcode.trim().length() <= 0) {
                    //抛出一个自定义的 AuthenticationException
                    throw new CheckCodeVerifyException("验证码没有输入");
                }
                //判断
                if(!checkcode.trim().equalsIgnoreCase(o_code.trim())) {
                    //抛出一个自定义的异常
                    throw new CheckCodeVerifyException("验证码输入不匹配");
                }
            } catch (AuthenticationException e) {
                //出现异常后，交由Spring Security的登录失败处理器来处理
                failureHandler.onAuthenticationFailure(request, response, e);
                //
                return ;
            }
        }
        // 如果不是 登录请求，则直接通过此过滤器
        filterChain.doFilter(request, response);
    }
}
